import { onMounted, onUnmounted } from 'vue'

// 键盘集中处理方法
// @TODO 性能优化
class Keyboard {
  keyState = new Set<string>()
  // 特殊修饰按键，系统有不同处理，有时候长按不会触发 repeat 为true
  specialModifierKey = new Set<string>(['alt'])
  constructor() {
    onMounted(() => {
      document.addEventListener('keydown', this.onKeydown.bind(this))
      document.addEventListener('keyup', this.onKeyUp.bind(this))
      document.addEventListener('visibilitychange', this.handleWindowBlur.bind(this))
      window.addEventListener('blur', this.handleWindowBlur.bind(this))
    })
    onUnmounted(() => {
      document.removeEventListener('keyup', this.onKeydown)
      document.removeEventListener('keyup', this.onKeyUp)
      document.removeEventListener('visibilitychange', this.handleWindowBlur)
      window.removeEventListener('blur', this.handleWindowBlur)
    })
  }

  private preprocess(e: KeyboardEvent) {
    if (e.isComposing || e.keyCode === 229) {
      return false
    }
    return true
  }

  // 监听键盘按下事件
  onKeydown(e: KeyboardEvent) {
    if (!this.preprocess(e)) return
    // console.log('onKeydown', e.code, e.key)
    if (e.repeat || this.specialModifierKey.has(e.key.toLocaleLowerCase())) {
      // 记录按压的键值
      this.keyState.add(e.key.toLowerCase())
    }
  }

  // 监听键盘松开事件
  onKeyUp(e: KeyboardEvent) {
    if (!this.preprocess(e)) return
    // console.log('onKeyUp', e.code, e.key)
    this.keyState.delete(e.key.toLowerCase())
  }

  // 判断键值是否被按下
  isPress(key: string) {
    return this.keyState.has(key.toLowerCase())
  }

  // window失去焦点: 重置所有按键
  handleWindowBlur() {
    this.keyState.clear()
  }
}

export const KeyboardEvent = Keyboard
